package com.sanjin.service.impl;

import com.sanjin.entity.Admin;
import com.sanjin.enums.RoleEnum;
import com.sanjin.exception.MyException;
import com.sanjin.repository.AdminRepository;
import com.sanjin.service.AdminService;
import com.sanjin.utils.JwtUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.List;

/**
 * @description:
 * @author: sanjin
 * @date: 2019/5/4 19:48
 */
@Service
public class AdminServiceImpl implements AdminService {

    @Autowired
    private AdminRepository repository;

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public String createToken(String username, String password) {
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        SecurityContextHolder.getContext().setAuthentication(authenticate);

        String token = jwtUtils.generateToken(repository.findByUsername(username));
        return token;
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public Admin register(Admin admin) {
        if (admin.getId() != null)
            throw new MyException("[createAdmin] 不能含有id");
        String username = admin.getUsername();
        String password = admin.getPassword();

        if (repository.findByUsername(username) != null)
            throw new MyException("该用户名已存在");
        Admin saveAdmin = new Admin();
        saveAdmin.setUsername(username);
        // 密码加密
        saveAdmin.setPassword(passwordEncoder.encode(password));
        // 新建用户默认 ROLE_USER 角色
        saveAdmin.setRole(RoleEnum.USER.roleName);
        return repository.save(saveAdmin);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public Admin queryAdminByUsername(String username) {

        return repository.findByUsername(username);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void deleteAdminsByIds(List<Integer> ids) {
        ids.forEach(id -> {
            repository.deleteById(id);
        });
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public Admin updateAdmin(Admin admin) {
        // update must have id
        if (admin.getId() == null)
            throw new MyException("there is a 'id' when update admin");

        // validate the role
        String[] split = admin.getRole().split(";");
        // 验证每个角色是否符合
        RoleEnum[] values = RoleEnum.values();
        boolean flag = true;
        for (String s : split) {
            for (int i = 0;i<values.length;i++) {
                if (values[i].roleName.equals(s)) {
                    // 存在角色
                    break;
                } else if (i == values.length - 1){
                    flag = false;
                }
            }
        }
        if (!flag)
            throw new MyException("您修改的角色不存在");

        repository.save(admin);
        return admin;
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public List<Admin> queryAdmins() {
        return repository.findAll();
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public Admin queryAdminById(Integer id) {
        Admin admin = repository.findById(id).orElse(null);
        if (admin == null)
            throw new MyException("用户id错误");
        return admin;
    }
}
